package com.person.mengshuai.mytestdemo.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.person.mengshuai.mytestdemo.annotation.DataLog;
import com.person.mengshuai.mytestdemo.entity.BDataLog;
import com.person.mengshuai.mytestdemo.exception.base.BusinessException;
import com.person.mengshuai.mytestdemo.mapper.BDataLogMapper;
import com.person.mengshuai.mytestdemo.satoken.UserInfo;
import com.person.mengshuai.mytestdemo.util.IpUtil;
import com.person.mengshuai.mytestdemo.util.UserInfoUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;

/**
 * 全局处理带有日志注解的切面类
 *
 * @author 孟帅
 * @since 2024/8/7
 */
@Aspect
@Component
public class LogAspect {
    @Autowired
    private BDataLogMapper dataLogMapper;

    @Pointcut("@annotation(com.person.mengshuai.mytestdemo.annotation.DataLog)")
    public void dsPointCut() {

    }

    @Around("dsPointCut()")
    private Object around(ProceedingJoinPoint joinPoint) throws BusinessException {
        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            throw new BusinessException(e.getMessage());
        } finally {
            insertDataLog(joinPoint, result);
        }
        return result;
    }

    private void insertDataLog(ProceedingJoinPoint joinPoint, Object result) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        DataLog dataLog = method.getAnnotation(DataLog.class);
        if (dataLog != null) {
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = method.getName();
            BDataLog bDataLog = new BDataLog();
            bDataLog.setClassName(className);
            bDataLog.setMethodName(methodName);
            bDataLog.setDescription(dataLog.desc());
            bDataLog.setType(dataLog.type().toString());
            UserInfo userInfo = UserInfoUtils.getUserInfo();
            if (userInfo != null) {
                bDataLog.setCreateBy(userInfo.getId());
            }
            bDataLog.setIp(IpUtil.getIp());
            Date date = new Date();
            bDataLog.setCreateTime(date);
            if (joinPoint.getArgs() != null) {
                bDataLog.setRequestParams(getParamsJson(joinPoint));
            }
            if (result != null) {
                bDataLog.setResponseResult(JSON.toJSONString(result.toString()));
            }
            dataLogMapper.insert(bDataLog);
        }
    }

    private String getParamsJson(ProceedingJoinPoint joinPoint) {
        // 参数值
        Object[] args = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] parameterNames = methodSignature.getParameterNames();

        // 通过map封装参数和参数值
        HashMap<String, Object> paramMap = new HashMap<>();
        for (int i = 0; i < parameterNames.length; i++) {
            paramMap.put(parameterNames[i], args[i]);
        }

        boolean isContains = paramMap.containsKey("request");
        if (isContains) paramMap.remove("request");
        return JSONObject.toJSONString(paramMap);
    }

}
